﻿/*************************************************************************
Sofia Public Transportation Client for WP7
    Copyright (C) 2011  Author: Tosho Toshev

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Windows.Navigation;
using System.Xml;
using System.Xml.Linq;
using System.Net.Browser;
using System.IO;
using HtmlAgilityPack;

/*-----------------------------------------------------------------------------------------------------------*/
/*
 * This is the main page of the manual Public transportation information!
 * The code is under the free GNU License v3.
 * This file is using the HtmlAgilityPack for WP7!
 * It parses the Sofia public transportation web page at: http://m.sumc.bg 
 * Check it at: http://htmlagilitypack.codeplex.com
 * The HTML Parsing is easier with it.
 */
/*-----------------------------------------------------------------------------------------------------------*/

namespace SofiaSKGTwp7
{

    public partial class MainPage : PhoneApplicationPage
    {
        private int ActiveParam;

        // Constructor=====================================================================================
        public MainPage()
        {
            InitializeComponent();
            // Set the data context of the listbox control to the sample data
            DataContext = App.ViewModel;
            this.Loaded += new RoutedEventHandler(MainPage_Loaded);

            ActiveParam = 0;
        }
        //==================================================================================================
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {

            App AppCls;

            AppCls = (App)Application.Current;

            try
            {

                //Tombstoning support on reactivation of the app
                if (State.ContainsKey("TRNAME"))
                {
                    AppCls.TRNAME = State["TRNAME"].ToString();
                    tbTRtype.Text = AppCls.TRNAME;
                }

                if (State.ContainsKey("LNAME"))
                {
                    AppCls.LNAME = State["LNAME"].ToString();
                    tbSelLine.Text = AppCls.LNAME;
                }

                if (State.ContainsKey("DIRNAME"))
                {
                    AppCls.DIRNAME = State["DIRNAME"].ToString();
                    tbDirection.Text = AppCls.DIRNAME;
                }

                if (State.ContainsKey("STNAME"))
                {
                    AppCls.STNAME = State["STNAME"].ToString();
                    tbStation.Text = AppCls.STNAME;
                }

                if (State.ContainsKey("DIRID"))
                {
                    AppCls.DIRID = (int)State["DIRID"];
                }

                if (State.ContainsKey("LID"))
                {
                    AppCls.LID = (int)State["LID"];
                }

                if (State.ContainsKey("STID"))
                {
                    AppCls.STID = (int)State["STID"];
                }

                if (State.ContainsKey("TRID"))
                {
                    AppCls.TRID = (int)State["TRID"];
                }
                // End of tombstoning routine
            }
            catch (Exception except)
            {
                MessageBox.Show("Couldn't restore the application!\r\nReason:"+except.Message);
            }


            IDictionary<string, string> parameters = this.NavigationContext.QueryString;

            if (parameters.ContainsKey("Active"))
            ActiveParam = int.Parse(parameters["Active"]);

            tbTRtype.Text    = AppCls.TRNAME;
            tbSelLine.Text   = AppCls.LNAME;
            tbDirection.Text = AppCls.DIRNAME;
            tbStation.Text   = AppCls.STNAME;

            base.OnNavigatedTo(e);
        }
        
        //==================================================================================================
        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            //TOMBSTONING OPERATIONS FOR WP7
            App AppCls;
            AppCls = (App)Application.Current;


            if (State.ContainsKey("TRNAME"))
                State.Remove("TRNAME");
            State.Add("TRNAME", AppCls.TRNAME);

            if (State.ContainsKey("LNAME"))
                State.Remove("LNAME");
            State.Add("LNAME", AppCls.LNAME);

            if (State.ContainsKey("DIRNAME"))
                State.Remove("DIRNAME");
            State.Add("DIRNAME", AppCls.DIRNAME);

            if (State.ContainsKey("STNAME"))
                State.Remove("STNAME");
            State.Add("STNAME", AppCls.STNAME);

            if (State.ContainsKey("DIRID"))
                State.Remove("DIRID");
            State.Add("DIRID", AppCls.DIRID);

            if (State.ContainsKey("LID"))
                State.Remove("LID");
            State.Add("LID", AppCls.LID);

            if (State.ContainsKey("STID"))
                State.Remove("STID");
            State.Add("STID", AppCls.STID);

            if (State.ContainsKey("TRID"))
                State.Remove("TRID");
            State.Add("TRID", AppCls.TRID);
            
            base.OnNavigatedFrom(e);
        }



        //Load data for the ViewModel Items==================================================================
        private void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            if (!App.ViewModel.IsDataLoaded)
            {
                App.ViewModel.LoadData();
            }
        }

        //Helper methods=====================================================================================

        private void SetTextBoxActive(TextBox ATb)
        {
            ActiveParam = int.Parse(ATb.Tag.ToString());

            string arguments = String.Format("?Active={0}", ActiveParam);

            NavigationService.Navigate(new Uri("/BindedList.xaml" + arguments, UriKind.Relative)); 
        }

        //TextBox Manipulation Events========================================================================

        private void tbTRtype_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
        {
            App AppCls;
            AppCls = (App)Application.Current;

            AppCls.LID   = -1;
            AppCls.DIRID = -1;
            AppCls.STID  = -1;

            AppCls.LNAME   = "";
            AppCls.DIRNAME = "";
            AppCls.STNAME  = "";
            
            SetTextBoxActive(tbTRtype);
        }
        //====================================================================================================
        private void tbSelLine_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
        {
            App AppCls;
            AppCls = (App)Application.Current;

            AppCls.DIRID = -1;
            AppCls.STID = -1;

            AppCls.DIRNAME = "";
            AppCls.STNAME = "";

            SetTextBoxActive(tbSelLine);
        }
        //====================================================================================================
        private void tbDirection_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
        {
            App AppCls;
            AppCls = (App)Application.Current;

            AppCls.STID = -1;

            AppCls.STNAME = "";

            SetTextBoxActive(tbDirection);
        }
        //====================================================================================================
        private void tbStation_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
        {
            SetTextBoxActive(tbStation);
        }

        //==================================================================================================

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            App AppCls;
            AppCls = (App)Application.Current;
            string strURL = "";
            if (tbStation.Text != "")
            {
                //Sending the bus stop ID as a parameter to the URL with leading zeros
                strURL = String.Format("http://m.sumc.bg/vt?q={0}&o=1&go=1", AppCls.STID.ToString("0000")); 

                WebClient wbClient = new WebClient();
                wbClient.DownloadStringAsync(new Uri(strURL));
                wbClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wbClient_DownloadStringCompleted);
            }
        }


        //HTML receiving event=================================================================================
        void wbClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            string Response = "";

            if (e.Error == null)
                Response = e.Result;
            else
                return;

            if (ParseHtmlDoc(Response))
            {
                NavigationService.Navigate(new Uri("/LineResults.xaml", UriKind.Relative)); 
            }
        }

        //HTML Document Parsing Routine=========================================================================
        //THE HTML OBJECT IN VERSION 7.0 IS BASIC SOME TRICKS ARE MADE HERE FOR NODE PARSING - NEEDS REFACTORING
        public bool ParseHtmlDoc(string htmlString)
        {
            bool Result = false;
            int TransID = 0;
            IEnumerable<HtmlParseError> htmlErrors;
            List<HtmlNode> TempList = new List<HtmlNode>();
            List<HtmlNode> NodeList = new List<HtmlNode>();

            HtmlDocument doc = new HtmlDocument();
            HtmlDocument lineDoc = new HtmlDocument();

            switch(((App)Application.Current).TRID)
            {
                case 0:
                    TransID = 3;
                        break;
                case 1:
                    TransID = 1;
                        break;
                case 2:
                    TransID = 2;
                        break;
            }

            try
            {
                doc.LoadHtml(htmlString);


                htmlErrors = doc.ParseErrors;

                NodeList = doc.DocumentNode.Descendants("body").ToList<HtmlNode>();
                
                //SEARCHING IN BODY TAG
                foreach (HtmlNode Node in NodeList)
                {
                    if (Node == null)
                        return false;
                    
                    TempList = Node.Descendants("div").ToList<HtmlNode>();
                    
                    //SEARCHING IN THE DIV TAGS
                    foreach (HtmlNode TmpNode in TempList)
                    {
                        //CHECKING AVAILABILITY
                        if (TmpNode == null)
                            return false;

                        if (!TmpNode.HasAttributes)
                            return false;
                        //END CHECKING

                        if (TmpNode.Attributes["class"] != null)
                        {
                            if (TmpNode.Attributes["class"].Value == "arr_info_" + TransID.ToString())
                            {
                                lineDoc.LoadHtml(TmpNode.InnerHtml);

                                //SEARCHING IF THE TRANSPORTATION LINE IS CORRECT
                                foreach (HtmlNode LineNode in lineDoc.DocumentNode.Descendants("a"))
                                {
                                    if (LineNode.InnerText == ((App)Application.Current).LNAME)
                                    {
                                        //Getting the transportation line number
                                        ((App)Application.Current).resLINE = LineNode.InnerText;

                                        //Getting the arrival time

                                        string HoursRes;

                                        HoursRes = TmpNode.InnerText.Replace("&nbsp;", "");
                                        HoursRes = HoursRes.Replace("-", "");
                                        HoursRes = HoursRes.Replace("(" + ((App)Application.Current).LNAME + ")", "");

                                        ((App)Application.Current).resHOURS = "\r\n Line: "+HoursRes;

                                        Result = true;
                                    }
                                } //END FOREACH
                            }
                        } 
   
                    } // END FOREACH TempList
                } //END FOREACH NodeList
            }
            catch (Exception e)
            {
                throw e;
            }
       
            return Result;
        }
    }
}